package com.almeros.android.multitouch.library;

import ohos.app.Context;
import ohos.multimodalinput.event.TouchEvent;

/**
 * @author Robert Nordan (robert.nordan@norkart.no)
 * <p>
 * Copyright (c) 2013, Norkart AS
 * <p>
 * All rights reserved.
 * <p>
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
 * <p>
 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the distribution.
 * <p>
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
 * OF SUCH DAMAGE.
 */
public class ShoveGestureDetector {

    private static final int INVALID_POINTER_INDEX = -1;
    private float fX, fY, sX, sY;
    private int mPointerIndex1, mPointerIndex2;
    private final OnShoveGestureListener mListener;
    private float mAlpha = 1;

    /**
     * Listener which must be implemented which is used by ShoveGestureDetector
     * to perform callbacks to any implementing class which is registered to a
     * ShoveGestureDetector via the constructor.
     */
    public interface OnShoveGestureListener {

        boolean onShove(ShoveGestureDetector detector);

        boolean onShoveBegin(ShoveGestureDetector detector);

        void onShoveEnd(ShoveGestureDetector detector);
    }

    /**
     * Helper class which may be extended and where the methods may be
     * implemented. This way it is not necessary to implement all methods
     * of OnShoveGestureListener.
     */
    public static class SimpleOnShoveGestureListener implements OnShoveGestureListener {

        public boolean onShove(ShoveGestureDetector detector) {
            return false;
        }

        public boolean onShoveBegin(ShoveGestureDetector detector) {
            return true;
        }

        public void onShoveEnd(ShoveGestureDetector detector) {
            // Do nothing, overridden implementation may be used
        }
    }

    public ShoveGestureDetector(OnShoveGestureListener listener) {
        mListener = listener;
        mPointerIndex1 = INVALID_POINTER_INDEX;
        mPointerIndex2 = INVALID_POINTER_INDEX;
    }

    public boolean onTouchEvent(TouchEvent event) {
        switch (event.getAction()) {
            case TouchEvent.PRIMARY_POINT_DOWN:
                sX = event.getPointerPosition(0).getX();
                sY = event.getPointerPosition(0).getY();
                mPointerIndex1 = event.getPointerId(0);
                break;
            case TouchEvent.OTHER_POINT_DOWN:
                fX = event.getPointerPosition(0).getX();
                fY = event.getPointerPosition(0).getY();
                mPointerIndex2 = event.getPointerId(event.getIndex());
                break;
            case TouchEvent.POINT_MOVE:
                if (mPointerIndex1 != INVALID_POINTER_INDEX && mPointerIndex2 != INVALID_POINTER_INDEX
                        && event.getPointerCount() > mPointerIndex2) {

                    float nfX, nfY, nsX, nsY;

                    nsX = event.getPointerPosition(mPointerIndex1).getX();
                    nsY = event.getPointerPosition(mPointerIndex1).getY();
                    nfX = event.getPointerPosition(mPointerIndex2).getX();
                    nfY = event.getPointerPosition(mPointerIndex2).getY();

                    calculateAlphaBetweenLines(nsX, nsY, nfX, nfY);

                    if (mListener != null) {
                        mListener.onShove(this);
                    }
                    sX = nsX;
                    sY = nsY;
                    fX = nfX;
                    fY = nfY;
                }
                break;
            case TouchEvent.PRIMARY_POINT_UP:
                mPointerIndex1 = INVALID_POINTER_INDEX;
                break;
            case TouchEvent.OTHER_POINT_UP:
                mPointerIndex2 = INVALID_POINTER_INDEX;
                break;
        }
        return true;
    }

    private void calculateAlphaBetweenLines(float sx1, float sy1, float sx2, float sy2) {
        float absX = Math.abs(sX - sx1);
        float absY = Math.abs(sY - sy1);

        float absXt = Math.abs(fX - sx2);
        float absYt = Math.abs(fY - sy2);

        if (fY > sy2){
            if (absX < 5 && absY <5 && absYt > 5){
                mAlpha = mAlpha - 0.05f;
            }
            if (absXt < 5 && absYt <5 && absY > 5){
                mAlpha = mAlpha - 0.05f;
            }
        }
        if (fY < sy2){
            if (absX < 5 && absY <5 && absYt > 5){
                mAlpha = mAlpha + 0.05f;
            }
            if (absXt < 5 && absYt <5 && absY > 5){
                mAlpha = mAlpha + 0.05f;
            }
        }
        if (sY > sy1 + 3 && fY > sy2 + 3 && absX < 5 && absXt < 5){
            mAlpha = mAlpha - 0.05f;
        }
        if (sY < sy1 - 3 && fY < sy2 - 3 && absX < 5 && absXt < 5){
            mAlpha = mAlpha + 0.05f;
        }
    }

    /**
     * Return the distance in pixels from the previous shove event to the current
     * event.
     *
     * @return The current distance in pixels.
     */
    public float getShovePixelsDelta() {
        return mAlpha;
    }
}
